#include <iostream>
#include <string>
#include <memory>

// 抽象电脑类
class Computer
{
public:
    void SetBoard(const std::string &board) { _board = board; }
    void SetDisplay(const std::string &display) { _display = display; }
    virtual void SetOs() = 0;
    void showed()
    {
        std::string computer = "Computer:\n";
        computer += "\tBoard: " + _board + "\n";
        computer += "\tDisplay: " + _display + "\n";
        computer += "\tOs: " + _os + "\n";
        std::cout << computer;
    }

protected:
    std::string _board;
    std::string _display;
    std::string _os;
};

// 具体电脑类
class MacBook : public Computer
{
public:
    void SetOs() override
    {
        _os = "Mac Os X12";
    }
};

// 抽象建造类
class Builder
{
public:
    virtual void Buildboard(const std::string board) = 0;
    virtual void Builddisplay(const std::string display) = 0;
    virtual void BuildOs() = 0;
    virtual std::shared_ptr<Computer> build() = 0;
};

// 具体建造类
class MacBookBuilder : public Builder
{
public:
    MacBookBuilder() : _computer(new MacBook) {}
    void Buildboard(const std::string board) override
    {
        _computer->SetBoard(board);
    }
    void Builddisplay(const std::string display) override
    {
        _computer->SetDisplay(display);
    }
    void BuildOs() override
    {
        _computer->SetOs();
    }
    std::shared_ptr<Computer> build() override
    {
        return _computer;
    }

private:
    std::shared_ptr<Computer> _computer;
};

// 指挥者类
class Director
{
public:
    Director(std::shared_ptr<Builder> builder) : _builder(builder) {}
    std::shared_ptr<Computer> construct(const std::string &board, const std::string &display)
    {
        _builder->Buildboard(board);
        _builder->Builddisplay(display);
        _builder->BuildOs();
        return _builder->build();
    }

private:
    std::shared_ptr<Builder> _builder;
};

int main()
{
    std::shared_ptr<Builder> builder(new MacBookBuilder);
    std::shared_ptr<Director> ptr(new Director(builder));
    std::shared_ptr<Computer> computer = ptr->construct("华硕主板", "三星显示器");
    computer->showed();
    return 0;
}